#include <mutex>
#include <QAudioFormat>
#include <QAudioOutput>
#include "AudioPlay.h"

class CAudioPlay : public AudioPlay
{
public:
    ~CAudioPlay() {
        if(output){
            delete output;
            output = NULL;
        }
    }
    QAudioOutput *output = NULL;
    QIODevice *io = NULL;
    // 互斥锁，用于保护outout和io变量，不被多个线程同时占用，进行线程同步
    std::mutex mux;

    // 调整音量
    virtual void SetVolume(double newVolume)
    {
        if(!output) return;
        output->setVolume(newVolume);
    }

    //返回缓冲中未播放的时间（ms）
    virtual long long GetNoPlayMs()
    {
        mux.lock();
        if(!output) {
            mux.unlock();
            return 0;
        }

        long long pts = 0;
        // 未播放字节数
        double size = output->bufferSize() - output->bytesFree();
        // 一秒音频字节数
        double secSize = sampleRate * (sampleRate / 8) * channels;

        if(secSize <= 0){
            pts = 0;
        } else {
            pts = (size / secSize) * 1000;
        }

        mux.unlock();
        return pts;
    }

    // 重置播放设备
    virtual void Clear()
    {
        mux.lock();
        if(io) io->reset();
        mux.unlock();
    }

    // 关闭视频
    virtual void Close()
    {
        mux.lock();
        if(io) {
            io->close();
            io = NULL;
        }
        if(output) {
            output->stop();
            delete output;
            output = 0;
        }
        mux.unlock();
    }

    // 打开视频
    virtual bool Open()
    {
        // 先把原来的关闭掉，释放资源
        Close();
        // 设置接下来解析音频的参数
        QAudioFormat fmt;
        fmt.setSampleRate(sampleRate);  // 采样率
        fmt.setSampleSize(sampleSize);  //
        fmt.setChannelCount(channels);  // 通道数
        fmt.setCodec("audio/pcm");      // pcm文件路径
        fmt.setByteOrder(QAudioFormat::LittleEndian);   // 字节序
        fmt.setSampleType(QAudioFormat::UnSignedInt);   // 采样类型
        mux.lock();
        output = new QAudioOutput(fmt);
        io = output->start(); //开始播放
        mux.unlock();
        if (io)
            return true;
        return false;
    }

    // 暂停
    virtual void SetPause(bool isPause)
    {
        mux.lock();
        if (!output)
        {
            mux.unlock();
            return;
        }
        if (isPause)
        {
            output->suspend(); // 暂停处理数据
        }
        else
        {
            output->resume(); // 从之前的暂停位置继续处理
        }
        mux.unlock();
    }

    // 播放
    virtual bool Write(const unsigned char *data, int datasize)
    {
        if(!data || datasize <= 0) return false;
        mux.lock();
        if (!output || !io)
        {
            mux.unlock();
            return false;
        }
        int size = io->write((char *)data, datasize);
        mux.unlock();
        if (datasize != size)
            return false;
        return true;
    }

    // 获取当前已播放的字节数
    virtual int GetFree()
    {
        mux.lock();
        if (!output)
        {
            mux.unlock();
            return 0;
        }
        int free = output->bytesFree();
        mux.unlock();
        return free;
    }

};

AudioPlay *AudioPlay::Get()
{
    static CAudioPlay play;
    return &play;
}

AudioPlay::AudioPlay()
{
}


AudioPlay::~AudioPlay()
{

}
